#pragma once
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string>
#include <cstring>
#include "Log.hpp"
#include "Err.hpp"
const static int gbacklog = 32;//全连接队列的长度
class Sock
{
public: 
    Sock()
        :_listenSocket(-1)
    {}
    ~Sock()
    {
        if(_listenSocket >= 0)
        {
            close(_listenSocket);
        }
    }
public:  
    void Socket();
    void Bind(int port);
    void Listen();
    int Accept(std::string *clientIp, uint16_t* clientPort, int* err);
    int GetListenSocket();
    void Close();
private:
    int _listenSocket;
};

void Sock::Socket()
{
    //1、创建监听socket套接字
    _listenSocket = socket(AF_INET, SOCK_STREAM, 0);
    if(_listenSocket < 0)
    {
        LogMessage(FATAL, "create socket error");
        exit(SOCKET_ERR);
    }
    LogMessage(NORMAL,"create socket success: %d", _listenSocket);
    //地址复用
    int opt = 1;
    setsockopt(_listenSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
}
void Sock::Bind(int port)
{
    //2、绑定端口号+ip地址
    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_addr.s_addr = INADDR_ANY;
    local.sin_family = AF_INET;
    local.sin_port=htons(port);
    if(bind(_listenSocket, (struct sockaddr*)&local, sizeof(local)) < 0)
    {
        LogMessage(FATAL, "bind socket error");
        exit(BIND_ERR);
    }
    LogMessage(NORMAL, "bind socket success");
}
void Sock::Listen()
{
    //3、设置监听状态
    if(-1 == listen(_listenSocket, gbacklog))
    {
        LogMessage(FATAL, "listen socket error");
        exit(LISTEN_ERR);
    }
    LogMessage(NORMAL, "listen socket success");
}
int Sock::Accept(std::string *clientIp, uint16_t* clientPort, int* err)
{
    //5、服务器获取客户端连接请求
    struct sockaddr_in peer;//输出型参数，拿到客户端的信息
    socklen_t len = sizeof(peer);
    int sock = accept(_listenSocket, (struct sockaddr*)&peer, &len);
    *err = errno;//带出错误码
    if(sock < 0)      
    {
        //LogMessage(ERROR, "accept error,next");
    }        
    else
    {
        //LogMessage(NORMAL, "accept a new link success");
        //提取客户端ip和端口号
        *clientIp = inet_ntoa(peer.sin_addr);
        *clientPort = ntohs(peer.sin_port);
    }   
    return sock;
}
int Sock::GetListenSocket()
{
    return _listenSocket;
}
void Sock::Close()
{
    if(_listenSocket >= 0)
    {
        close(_listenSocket);
    }
}
